﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.SceneManagement;
using Object = UnityEngine.Object;

namespace Utility.AssetTools
{
	public static class AssetDatabaseEX
	{
		/// <summary>
		/// Create directory if not exist
		/// </summary>
		/// <param name="path">relative to Assets/</param>
		public static void CreateDirectory (string path)
		{
			Directory.CreateDirectory (Application.dataPath + "/" + path);
		}

		/// <summary>
		/// Get or create a ScriptableObject of given name
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="directory">relative to Assets/</param>
		/// <param name="name"></param>
		/// <param name="asset"></param>
		/// <returns></returns>
		public static bool GetOrCreateScriptableObject<T> (string directory, string name, out T asset, bool forceCreate = false)
			where T : ScriptableObject
		{
			asset = null;
			if (string.IsNullOrWhiteSpace (name))
			{
				asset = null;
				Debug.LogWarning ("asset name is null or empty!");
				return false;
			}

			//create folder if needed
			CreateDirectory (directory);

			//try find asset
			string path = "Assets/" + directory + name + ".asset";
			asset = AssetDatabase.LoadAssetAtPath<T> (path);

			//create new
			if (asset == null || forceCreate)
			{
				asset = ScriptableObject.CreateInstance<T> ();
				asset.name = name;
				AssetDatabase.CreateAsset (asset, path);
				Debug.Log ("New asset created: " + path);
				return true;
			}
			return false;
		}

		public static void ReimportAsset (Object asset)
		{
			string path = AssetDatabase.GetAssetPath (asset);
			if (!string.IsNullOrEmpty (path))
			{
				AssetDatabase.ImportAsset (path);
			}
		}

		public static Object FindSubAsset (Object mainAsset, Type subAssetType, string name = null)
		{
			if (!AssetDatabase.IsMainAsset (mainAsset))
			{
				Debug.LogWarning ("This is not main asset");
				return null;
			}

			//try find
			string path = AssetDatabase.GetAssetPath (mainAsset);
			Object[] subassets = AssetDatabase.LoadAllAssetRepresentationsAtPath (path);
			foreach (Object asset in subassets)
			{
				if (asset != null)
				{
					var type = asset.GetType ();
					if (subAssetType.IsAssignableFrom (type))
					{
						if (name == null || asset.name == name)
						{
							return asset;
						}
					}
				}
			}

			return null;
		}

		public static T FindSubAsset<T> (Object mainAsset, string name = null)
		{
			return (T)(object)FindSubAsset (mainAsset, typeof (T), name);
		}

		public static Object[] FindSubAssets (Object mainAsset, Type subAssetType = null)
		{
			if (!AssetDatabase.IsMainAsset (mainAsset))
			{
				Debug.LogWarning ("This is not main asset");
				return null;
			}

			//try find
			string path = AssetDatabase.GetAssetPath (mainAsset);
			Object[] subassets = AssetDatabase.LoadAllAssetRepresentationsAtPath (path);
			if (subAssetType == null)
			{
				return subassets;
			}
			else
			{
				return subassets.Where (obj => obj != null && subAssetType.IsAssignableFrom (obj.GetType ())).ToArray ();
			}
		}

		public static T[] FindSubAssets<T> (Object mainAsset)
		{
			return Array.ConvertAll (FindSubAssets (mainAsset, typeof (T)), obj => (T)(object)obj);
		}

		public static string GetSceneFolder (Scene scene, bool create = false)
		{
			string path = scene.path;
			if (string.IsNullOrEmpty (path))
			{
				Debug.LogError ("Scene path is null, scene is not saved");
			}

			string suffix = ".unity";
			path = path.Replace (suffix, "/");

			if (create)
			{
				CreateDirectory (path);
			}
			return path;
		}



		public static List<T> LoadAllAssetsAtPath<T> (string path) where T : UnityEngine.Object
		{
			List<T> results = new List<T> ();
			if (path.StartsWith ("Assets"))
			{
				path = path.Substring (path.IndexOf ('/') + 1);
			}
			if (path.Contains ("."))
			{
				path = path.Substring (0, path.LastIndexOf ('/'));
			}

			string fullPath = Application.dataPath + "/" + path;
			if (!Directory.Exists (fullPath))
			{
				Directory.CreateDirectory (fullPath);
			}

			string[] arrStrAudioPath = Directory.GetFiles (fullPath, "*", SearchOption.AllDirectories);
			//循环遍历每一个路径，单独加载
			foreach (string strAudioPath in arrStrAudioPath)
			{
				//替换路径中的反斜杠为正斜杠       
				string strTempPath = strAudioPath.Replace (@"\", "/");
				//截取我们需要的路径
				strTempPath = strTempPath.Substring (strTempPath.IndexOf ("Assets"));

				if (strTempPath.EndsWith (".meta"))
				{
					continue;
				}

				//根据路径加载资源
				T asset = AssetDatabase.LoadAssetAtPath<T> (@strTempPath);
				if (asset != null)
				{
					results.Add (asset);
				}
				else
				{
					continue;
				}
			}
			return results;
		}
	}

}